2

JS从入门到放弃-基本类型和引用类型

JS有number,string,null,undefined,boolean,array,object七种数据类型,而JS的变量,根据指向数据类型的不同,也分为两种类型,一种基本类型,一种引用类型.

1. 基本类型

基本类型包括: number, string, null, undefined, boolean这五种.但凡变量指向这五种数据类型的都称之为基本类型.

var test1 = 'hahaha'; // string
var test2 = 1; // number
var test3 = true; // boolean

假设有以上变量,那么他们在内存中栈区的存储结构大概是这样子的.

栈区指针 栈区值
test1 hahaha
test2 1
test3 true
var test = '321';
var test = '123';
var test1 = test;
console.log(test === test1); // true

执行以上语句之后,你可能会觉得变量test的值从字符串'321'变成了字符串'123'.并不是值改变了,而是test只是一个指针,上面的两条语句都只是在为同一个指针指向不同的值而已.值是不可被改变的.执行第三条语句的时候,首先初始化一个test1变量,然后把test的变量赋值给test1.这种赋值称为深拷贝.如图:

指针
test '123'
test1 '123'

最后一条语句之间的比较其实是testtest1之间的值作比较.也就是console.log('123' === '123'),之所以多此一举的解释最后两条语句,原因是因为引用类型的赋值和比较并不是如此.

2. 引用类型

引用类型包括: object和array这两种.但凡变量指向这两种数据类型的都称之为引用类型.

var china = {
  tianjin: '天津',
  beijing: '北京'
};
var huabei = {
  tianjin: '天津',
  beijing: '北京'
};

假设有以上变量,那么他们在内存中栈区堆区的存储结构大概是这样子的.

栈区指针 栈区值
china china对象在堆区的内存地址
huabei huabei对象在堆区的内存地址
堆区地址 堆区值
china对象在堆区的内存地址 china对象
huabei对象在堆区的内存地址 huabei对象
china.handan = '邯郸';
console.log(china.handan); // '邯郸'

当我们继续执行上面语句的时候china堆区值内部的属性除了原有的tianjinbeijing之外又动态的添加了一个handan属性.这说明引用类型的值是可以被改变的.

console.log(china === huabei);  // false

china对象和huabei对象内的属性明明一样,但是完全相等比较符却返回了false.这进一步证明了引用类型的比较是比较两者在堆区的地址是否相同.如果我们对两个对象的内部的属性进行比较呢.

console.log(china.tianjin === huabei.tianjin) // true

这里又会返回true,这是因为我们做比较的对象的属性是基本类型.他们会比较内部的值,而不是比较两者在堆区内的地址.

最后说一下引用类型的赋值.继续上面的代码

var asia = china;
asia.tianjin = '红桥';
console.log(asia.tianjin); // 红桥
console.log(china.tianjin); // 红桥

执行上面语句你会发现明明改变的是asia的属性,但是china的属性也跟着改变了.这是因为赋给asia的值是china对象在堆区的内存地址,而不是china对象本身.两者实际上指向同一个堆区对象.也因此,改变其中任何一个的属性,另外一个也会随之更改.这种赋值也称之为浅拷贝.

栈区指针 栈区值
china china对象在堆区的内存地址
asia china对象在堆区的内存地址
堆区地址 堆区值
china对象在堆区的内存地址 china对象
总结

基本类型:值不可变,存放于栈区,相互比较是基于值进行比较,相互赋值是深拷贝赋值.
引用类型:值可改变,同时存放于栈区和堆区,相互比较是基于在堆区内的地址,相互赋值是浅拷贝.


重重重重重楼
13 声望2 粉丝

github地址:[链接]